home *** CD-ROM | disk | FTP | other *** search
- unit MyScroll;
- interface
- uses
- MyGlobals;
-
- procedure AdjustScrollBars; {reset max of scroll bars}
- procedure AdjustText (pane: integer); {scroll to scrollbar value}
- procedure ScrollCharacter; {scroll selection into view}
- procedure ScrollToSelection; { figure which way to scroll}
- procedure SetEditText (Index: integer); {Switch EditText to proper pane}
- procedure FixTextRects; {resize EditText's rectangles and recalculate line starts}
- procedure FixScrollbarRects; {resize and postion scroll/split bars}
- procedure UpdateOtherPane; {invalidate non active pane's update area}
-
- implementation
-
- { LinesInText is a kluge necessitated by a minor bug in TE. The bug is that if the last }
- { character in the TE text buffer is a Carriage Return, the field "nLines" may be off by one, }
- { and cause slightly incorrect updating of the window. This routine always returns the}
- { correct number of lines in the buffer. This is taken from Symantec's Think's Pascal}
- function LinesInText: integer;
- var
- lines: integer;
- txt: CharsHandle;
- begin
- with EditText^^ do
- begin
- lines := nLines;
- txt := CharsHandle(hText);
- if teLength > 0 then
- if txt^^[teLength - 1] = CR then {Carriage Return?}
- lines := lines + 1;
- LinesInText := lines
- end
- end; {of LinesInText}
-
- procedure AdjustScrollBars; {reset max of scroll bars}
- var
- ctlMax, index, height: integer;
- begin
- for index := 1 to 2 do {for each pane}
- begin
- SetEditText(index); {set pane}
- with EditText^^ do
- begin
- height := (viewRect.bottom - viewRect.top) div lineHeight; {lines of text in viewRect}
- ctlMax := LinesInText - height; {Control max}
- if ctlMax < 0 then
- ctlMax := 0;
- SetCtlMax(Scroll[index], ctlMax)
- end
- end;
- SetEditText(activePane); {reset EditText back to active pane}
- end; {of AdjustScrollBars}
-
- procedure AdjustText; {scroll to scrollbar value}
- var
- oldScroll, newScroll, delta: integer;
- begin
- SetEditText(pane);
- with EditText^^ do
- begin
- oldScroll := viewRect.top - destrect.top; {get old scroll value}
- newScroll := GetCtlValue(Scroll[pane]) * lineHeight; {get new scroll value}
- delta := oldScroll - newScroll;
- if delta <> 0 then
- begin
- TEScroll(0, delta, EditText); {scroll to new value}
- end;
- end;
- destRect[pane] := EditText^^.destRect; {reset destRect for switching}
- SetEditText(activepane); {reset to active pane}
- end; {of AdjustText}
-
- procedure ScrollCharacter; {scroll selection into view}
- var
- theLine, height: integer;
- begin
- HLock(Handle(EditText));
- theLine := 0;
- with EditText^^ do
- begin
- height := (viewRect.bottom - viewRect.top) div lineHeight;
- while selStart >= lineStarts[theLine] do
- theLine := theLine + 1;
- SetCtlValue(Scroll[activePane], theLine - nLines div 2);
- AdjustText(activePane);
- end;
- HUnLock(Handle(EditText));
- end; {of scroll character}
-
- procedure ScrollToSelection; {Figure which way to scroll to get selection}
- var
- topline, bottomline, height, max: integer;
- begin
- SetEditText(activePane);
- HLock(Handle(EditText));
- AdjustScrollBars;
- AdjustText(activePane);
- with EditText^^, viewRect do
- begin
- topline := GetCtlValue(Scroll[activePane]);
- height := (bottom - top) div lineHeight;
- bottomline := topline + height;
- max := GetCtlMax(Scroll[activePane]);
- if max = 0 then {all text within pane}
- AdjustText(activePane)
- else
- ScrollCharacter; {need to scroll}
- end;
- HUnLock(Handle(EditText));
- end; {of ScrollToSelection}
-
- procedure SetEditText;
- {Set EditText to indexed pane}
- begin
- EditText^^.viewRect := viewRect[Index];
- EditText^^.destRect := destRect[Index];
- end; {of SetEditText}
-
- procedure FixTextRects; {adjust EditText's two panes}
- begin
- HLock(Handle(EditText));
- viewRect[1] := MyWindow^.portRect; {set lower pane}
- viewRect[1].top := Split^^.contrlValue + IndicatorWidth;
- viewRect[1].right := viewRect[1].right - SBarWidth;
- viewRect[1].bottom := viewRect[1].bottom - SBarWidth;
- InsetRect(viewRect[1], Margin, Margin); {Give TE margins}
-
- {Make viewRect a Multiple of lineHeight}
- viewRect[1].bottom := viewRect[1].bottom - ((viewRect[1].bottom - viewRect[1].top) mod EditText^^.lineHeight);
- destRect[1] := viewRect[1]; {Set destRect}
-
- viewRect[2] := MyWindow^.portRect; {set upper pane}
- viewRect[2].bottom := Scroll[2]^^.contrlRect.bottom;
- viewRect[2].right := viewRect[2].right - SBarWidth;
- InsetRect(viewRect[2], Margin, Margin); {Give TE margins}
-
- {Make viewRect a multiple of lineHeight}
- viewRect[2].bottom := viewRect[2].bottom - ((viewRect[2].bottom - viewRect[2].top) mod EditText^^.lineHeight);
- destRect[2] := viewRect[2];
-
- SetEditText(activePane); {Reset EditText back to active pane}
-
- if EditText <> nil then {recalculate line starts}
- begin
- TECalText(EditText);
- AdjustText(1);
- AdjustText(2);
- ScrollToSelection;
- end;
- HUnLock(Handle(EditText));
- end; {of FixTextRects}
-
- procedure FixScrollbarRects; {adjust scrollbars according to splitbar}
- var
- width, hieght: integer;
- temp: rect;
- begin
- with MyWindow^.portRect do {get window dimensions}
- begin
- hieght := bottom - top - SBarWidth + 1;
- width := right - left - SBarWidth + 1;
- end;
-
- SetRect(temp, width, 0, width + SBarWidth, hieght); {set control rectangles}
- Split^^.contrlRect := temp;
- Scroll[1]^^.contrlRect := Split^^.contrlRect;
- Scroll[2]^^.contrlRect := Split^^.contrlRect;
- Scroll[1]^^.contrlRect.top := Split^^.contrlValue + IndicatorWidth;
- Scroll[2]^^.contrlRect.bottom := Split^^.contrlValue;
-
- {check to see if there is enough room to draw scroll bars}
- if (Scroll[2]^^.contrlRect.bottom - Scroll[2]^^.contrlRect.top) < SBarMinLen then
- begin {not enough room, make invisible}
- EraseRect(Scroll[2]^^.contrlRect);
- Scroll[2]^^.contrlVis := invisible;
- end
- else {enough room, make visible}
- Scroll[2]^^.contrlVis := visible;
-
- if (Scroll[1]^^.contrlRect.bottom - Scroll[1]^^.contrlRect.top) < SBarMinLen then
- begin {not enough room, make invisible}
- EraseRect(Scroll[1]^^.contrlRect);
- Scroll[1]^^.contrlVis := invisible;
- end
- else {enough room, make visible}
- Scroll[1]^^.contrlVis := visible;
-
- if EditText <> nil then {fix TE rectangles}
- begin
- FixTextRects;
- EraseRect(MyWindow^.portRect);
- InvalRect(MyWindow^.portRect);
- end;
- end;{ of FixScrollbarRects}
-
- procedure UpdateOtherPane; {invalidate non active pane for updating}
- var
- tempRect: array[1..2] of rect;
- delta: array[1..2] of integer;
- i, index: integer;
- pane: rect;
- intersect: boolean;
- begin
- case activePane of {get non active pane}
- 1:
- index := 2;
- 2:
- index := 1;
- end;
-
- for i := 1 to 2 do {normalize viewRects to check for overlapp}
- begin
- delta[i] := destRect[i].top;
- tempRect[i] := viewRect[i];
- OffsetRect(tempRect[i], 0, -delta[i]);
- end;
-
- intersect := SectRect(tempRect[1], tempRect[2], pane); {get intersection}
- OffsetRect(pane, 0, delta[index]); {place intersection to correct area on window}
-
- if intersect then {invalidate intersecting rectangle}
- InvalRect(pane);
- end; {of UpdateOtherPane}
-
- end.